<template>
  <div>
    <div class="flex">
      <div class="left">
        <el-collapse v-model="activeNames">
          <el-collapse-item title="可拖拽元素库" name="1">
            <div
              class="btn"
              v-for="(item, index) in List"
              :key="index"
              :title="item"
              @mousedown="startDragToGraph(item, $event)"
            >
              <el-link :underline="false" :disabled="item.disabled">
                {{ item.name }}
              </el-link>
            </div>
          </el-collapse-item>
        </el-collapse>
      </div>
      <div class="right" id="container"></div>
    </div>
  </div>
</template>
<script>
import { Graph } from '@antv/x6'
import { Snapline } from '@antv/x6-plugin-snapline'
import { Dnd } from '@antv/x6-plugin-dnd'
export default {
  data() {
    return {
      graph: null,
      // 节点
      nodes: [
        {
          id: 'node1',
          shape: 'rect',
          x: 40,
          y: 40,
          width: 100,
          height: 40,
          label: 'hello',
          attrs: {
            body: {
              stroke: '#8f8f8f',
              strokeWidth: 1,
              fill: '#fff',
              rx: 6,
              ry: 6,
            },
          },
        },
        {
          id: 'node2',
          shape: 'rect',
          x: 160,
          y: 180,
          width: 100,
          height: 40,
          label: 'world',
          attrs: {
            body: {
              stroke: '#8f8f8f',
              strokeWidth: 1,
              fill: '#fff',
              rx: 6,
              ry: 6,
            },
          },
        },
      ],
      // 边
      edges: [
        {
          shape: 'edge',
          source: 'node1',
          target: 'node2',
          label: 'x6',
          attrs: {
            line: {
              stroke: '#8f8f8f',
              strokeWidth: 1,
            },
          },
        },
      ],
      // 拖拽
      activeNames: ['1'],
      // 此处提前定义好的假数据，也可利用接口请求从后端获取，相关参数可以自己定义
      List: [
        {
          id: 1,
          name: '目录监听',
          disabled: true,
        },
        {
          id: 2,
          name: '数据组织',
          disabled: false,
        },
        {
          id: 3,
          name: '影像发布',
          disabled: true,
        },
        {
          id: 4,
          name: '目标检测',
          disabled: false,
        },
        {
          id: 5,
          name: '变化检测',
          disabled: true,
        },
        {
          id: 6,
          name: '地物分类',
          disabled: true,
        },
        {
          id: 7,
          name: '专家候审',
          disabled: false,
        },
        {
          id: 8,
          name: '样本入库',
          disabled: true,
        },
        {
          id: 9,
          name: '影像入库',
          disabled: false,
        },
        {
          id: 10,
          name: '目标入库',
          disabled: true,
        },
        {
          id: 11,
          name: '图幅整饰',
          disabled: false,
        },
        {
          id: 12,
          name: '打包下载',
          disabled: true,
        },
      ],
    }
  },
  mounted() {
    this.graph = new Graph({
      container: document.getElementById('container'),
      width: 800,
      height: 600,
      background: {
        color: '#F2F7FA',
      },
      // 网格线设置
      grid: {
        visible: true,
        type: 'doubleMesh',
        args: [
          {
            color: '#eee', // 主网格线颜色
            thickness: 1, // 主网格线宽度
          },
          {
            color: '#ddd', // 次网格线颜色
            thickness: 1, // 次网格线宽度
            factor: 4, // 主次网格线间隔
          },
        ],
      },
      // 缩放与平移
      mousewheel: true, //使用滚轮控制缩放
      panning: {
        enabled: true,
        //触发键盘事件进行平移：'alt' | 'ctrl' | 'meta' | 'shift'
        modifiers: [],
        //触发鼠标事件进行平移：'leftMouseDown' | 'rightMouseDown' | 'mouseWheel'
        eventTypes: ['leftMouseDown'],
      },
    })
    // 渲染节点和边
    this.graph.fromJSON({
      nodes: this.nodes,
      edges: this.edges,
    })
    // 实现画布内容居中
    this.graph.centerContent()
    //增加对齐线
    this.graph.use(
      new Snapline({
        enabled: true,
      })
    )
  },
  methods: {
    // 自定义一个拖拽方法，也可以单独封装成一个js文件(方便调用)
    // 这里直接写到vue文件的methods方法里了
    // 需求：未置灰的可以拖拽，置灰的无法拖拽即禁用状态
    startDragToGraph(item, e) {
      if (item.disabled == false) {
        const node = this.graph.createNode({
          // 自己设置拖拽元素的具体属性，此处不赘述
          width: 40, //节点的宽度
          height: 180, //节点的高度
          attrs: {
            body: {
              fill: '#fff',
              stoke: '#000',
            },
            text: {
              text: item.name,
              textWrap: {
                width: '50%', // 宽度减少 10px
                height: '100%', // 高度为参照元素高度的一半
                ellipsis: true, // 文本超出显示范围时，自动添加省略号
              },
            },
          },
        })
        const dnd = new Dnd({
          target: this.graph,
          // ☆拖拽结束时，验证节点是否可以放置到目标画布中。
          validateNode: () => {
            console.log('成功拖拽至目标画布')
          },
        })
        dnd.start(node, e)
      } else {
        return
      }
    },
  },
}
</script>
<style scoped>
.flex {
  display: flex;
}
.left {
  width: 150px;
  padding: 10px;
  border: 1px solid blue;
}
.right {
  margin-left: 10px;
  border: 1px solid blue;
}
.btn {
  cursor: move;
}
</style>